/*
 * $Id: Widget.java 122 2009-05-12 15:54:07Z meyer@alphatec.de $
 * 
 *
 * Copyright 2009 DeltaDesk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package deltadesk.gui.deltagui.widget;

import java.awt.Color;
import java.awt.Font;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import deltadesk.gui.deltagui.layout.Layoutable;

/**
 * Widget.
 * 
 * @author Andreas Meyer
 * @version $Revision: 122 $
 */
public abstract class Widget implements Layoutable {
	
	/** The x location of this widget relative to its container. */
	private int x;

	/** The y location of this widget relative to its container. */
	private int y;

	/** The width of the widget. */
	private int width;

	/** The height of the widget. */
	private int height;

	/** The preferred width of the widget. */
	private int preferredWidth;

	/** The preferred height of the widget. */
	private int preferredHeight;

	/** The background color. */
	private Color backgroundColor;

	/** The border color. */
	private Color borderColor;

	/** The font of this component. */
	private Font font = new Font("Verdana", Font.PLAIN, 12);

	/** The name of the widget. */
	private String name;
	
	/** The data object. */
	private Object data;
	
	/** Thread pool for event notification. */
	static final ThreadPoolExecutor tpe;

	static {

		tpe = new ThreadPoolExecutor(1,   // core pool size
				                     5,  // max pool size
				                     300, // keep alive time 
				                     TimeUnit.SECONDS,
				                     new ArrayBlockingQueue<Runnable>(500),
				     				 new ThreadPoolExecutor.DiscardOldestPolicy());
	}


	/**
	 * Construct the widget.
	 * 
	 */
	public Widget() {
		this(null);
	}
	
	/**
	 * Construct the widget.
	 * 
	 * @param layout
	 * @param name
	 */
	public Widget(final String name) {

		this.name = name;

		// set defaults
		setBackgroundColor(Color.GRAY);
		setPreferredSize(64, 64);
	}

	/**
	 * @return the x
	 */
	public final int getX() {
		return x;
	}

	/**
	 * @param x the x to set
	 */
	public final void setX(final int x) {
		setLocation(x, this.y);
	}

	/**
	 * @return the y
	 */
	public final int getY() {
		return y;
	}

	/**
	 * @param y the y to set
	 */
	public final void setY(final int y) {
		setLocation(this.x, y);
	}

	/**
	 * @see deltadesk.gui.deltagui.layout.Layoutable#setLocation(int, int)
	 */
	public final void setLocation(final int x, final int y) {

		if(this.x != x || this.y != y) {

			this.x  = x;
			this.y = y;

			tpe.execute(new Runnable() { public void run() { 
				onMove(); 
			}});
		} // end if
	}

	/**
	 * @return the width
	 */
	public final int getWidth() {
		return width;
	}

	/**
	 * @param width the width to set
	 */
	public final void setWidth(final int width) {
		setSize(width, this.height);
	}

	/**
	 * @return the height
	 */
	public final int getHeight() {
		return height;
	}

	/**
	 * @param height the height to set
	 */
	public final void setHeight(final int height) {
		setSize(this.width, height);
	}

	/**
	 * @see deltadesk.gui.deltagui.layout.Layoutable#setSize(int, int)
	 */
	public final void setSize(final int width, final int height) {
		
		if(this.width != width || this.height != height) {

			this.width  = width;
			this.height = height;

			tpe.execute(new Runnable() { public void run() { 
				onResize();
			}});
		} // end if
	}

	/**
	 * @see deltadesk.gui.deltagui.layout.Layoutable#getPreferredWidth()
	 */
	public final int getPreferredWidth() {
		return preferredWidth;
	}

	/**
	 * @param preferredWidth the preferredWidth to set
	 */
	public final void setPreferredWidth(final int preferredWidth) {
		this.preferredWidth = preferredWidth;
	}

	/**
	 * @see deltadesk.gui.deltagui.layout.Layoutable#getPreferredHeight()
	 */
	public final int getPreferredHeight() {
		return preferredHeight;
	}

	/**
	 * @param preferredHeight the preferredHeight to set
	 */
	public final void setPreferredHeight(final int preferredHeight) {
		this.preferredHeight = preferredHeight;
	}

	/**
	 * Set the preferred size.
	 * 
	 * @param preferredWidth
	 * @param preferredHeight
	 */
	public final void setPreferredSize(final int preferredWidth,
			                     final int preferredHeight) {
		
		this.preferredWidth  = preferredWidth;
		this.preferredHeight = preferredHeight;
	}

	/**
	 * @return the backgroundColor
	 */
	public final Color getBackgroundColor() {
		return backgroundColor;
	}

	/**
	 * @param backgroundColor the backgroundColor to set
	 */
	public final void setBackgroundColor(final Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	/**
	 * @return the borderColor
	 */
	public final Color getBorderColor() {
		return borderColor;
	}

	/**
	 * @param borderColor the borderColor to set
	 */
	public final void setBorderColor(final Color borderColor) {
		this.borderColor = borderColor;
	}

	/**
	 * @return the font
	 */
	public final Font getFont() {
		return font;
	}

	/**
	 * @param font the font to set
	 */
	public final void setFont(final Font font) {
		this.font = font;
	}

	/**
	 * @return the name
	 */
	public final String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public final void setName(final String name) {
		this.name = name;
	}

	/**
	 * @return the data
	 */
	public final Object getData() {
		return data;
	}

	/**
	 * @param data the data to set
	 */
	public final void setData(final Object data) {
		this.data = data;
	}
	
	/** Event for component resize. */
	protected void onResize() {}

	/** Event for component move. */
	protected void onMove() {}

	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		
		final StringBuffer sb = new  StringBuffer();
		
		sb.append(getClass().getSimpleName());
		sb.append("[");
		sb.append(name);
		sb.append("] Location=");
		sb.append(getX());
		sb.append(",");
		sb.append(getY());
		sb.append(" Size=");
		sb.append(getWidth());
		sb.append(",");
		sb.append(getHeight());
	
		return sb.toString();
	}

}
